// 版权所有2010 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build aix | | darwin | | | dragonfly | | freebsd | | linux | | netbsd | | openbsd | | solaris 

package exec

import (
	"errors"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

// ErrNotFound。
var ErrNotFound = errors.New("executable file not found in $PATH")

func findExecutable(file string) error {
	d, err := os.Stat(file)
	if err != nil {
		return err
	}
	if m := d.Mode(); !m.IsDir() && m&0111 != 0 {
		return nil
	}
	return fs.ErrPermission
}

// LookPath在由PATH环境变量命名的
// 目录中搜索名为文件的可执行文件。
// 如果文件包含斜杠，则直接尝试，不参考路径。
// 结果可能是绝对路径，也可能是相对于当前目录的路径。
func LookPath(file string) (string, error) {
	// 注意（rsc）：我希望我们可以在这里使用Plan 9行为
	// （仅当文件以/或/或..
	// 但这与所有Unix shell不匹配。

	if strings.Contains(file, "/") {
		err := findExecutable(file)
		if err == nil {
			return file, nil
		}
		return "", &Error{file, err}
	}
	path := os.Getenv("PATH")
	for _, dir := range filepath.SplitList(path) {
		if dir == "" {
			// Unix shell语义：path元素“”的意思是“”
			dir = "."
		}
		path := filepath.Join(dir, file)
		if err := findExecutable(path); err == nil {
			return path, nil
		}
	}
	return "", &Error{file, ErrNotFound}
}
